package uk.ac.open.kmi.dyniqx.repositories;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;

import org.apache.commons.httpclient.DefaultHttpMethodRetryHandler;
import org.apache.commons.httpclient.HostConfiguration;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.params.HttpMethodParams;
import org.apache.log4j.Logger;
import org.apache.lucene.document.Field;
import org.directwebremoting.WebContext;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import uk.ac.open.kmi.dyniqx.storages.Storage;

public class GoogleVideoThread extends Thread {
	
	public String queryString;
	public int count;

	public Storage storage;
	public WebContext wctx;
	
	public volatile boolean stop = false;
	
	public Logger logger = Logger.getLogger("uk.ac.open.kmi.dyniqx.repositories.GoogleVideoThread");
	
	public GoogleVideoThread(Storage storage, WebContext wctx, String queryString, int count) {
		
		this.setStorage(storage);
		this.setWctx(wctx);
		this.setQueryString(queryString);
		this.setCount(count);
		 
	}

	@SuppressWarnings("unchecked")
	public void run() {
		
		this.logger.debug("Thread started.");
		
		String searchUrl = "";
		try {
			searchUrl = "http://ajax.googleapis.com/ajax/services/search/video?v=1.0&q=" + URLEncoder.encode(this.getQueryString(), "UTF-8");
		} catch (UnsupportedEncodingException e1) {
			e1.printStackTrace();
		}
		
		if (this.count > 20) this.count = 20;
		int startIndex = 0;
		int max = 4;
		int temp_count = 0;
		
		/* Open University proxy Settings */

		System.getProperties().put( "proxySet", "true" );
		System.getProperties().put( "proxyHost", "wwwcache" );
		System.getProperties().put( "proxyPort", "80" );
		System.setProperty("java.net.useSystemProxies","true");

		HttpClient client = new HttpClient();
		HostConfiguration hhc = client.getHostConfiguration();
		
		/* Open University proxy Settings */

	    hhc.setProxy("wwwcache", 80);
	    
		client.setHostConfiguration(hhc);		
		
		GetMethod method;
		
		String line;
	    StringBuilder builder;
	    BufferedReader reader;
		
	    JSONObject json;
	    JSONArray jsonArray;
	    
	    int results;
	    
	    org.apache.lucene.document.Document result = null;
	    ArrayList<org.apache.lucene.document.Document> documentArray = null;
	    
	    String summary;
	    
		try {
			
			while ((startIndex < this.count) && !stop) {
				
				temp_count = 0;
								
			    method = new GetMethod(searchUrl + "&start=" + startIndex + "&ndsp=" + max);
			    
			    method.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, new DefaultHttpMethodRetryHandler(3, false));
			    int statusCode = client.executeMethod(method);
			    if (statusCode != HttpStatus.SC_OK) {
			        System.err.println("Method failed: " + method.getStatusLine());
			    }

			    line = "";
			    builder = new StringBuilder();
			    reader = new BufferedReader(new InputStreamReader(method.getResponseBodyAsStream()));
			    while((line = reader.readLine()) != null) {
			    	builder.append(line);
			    }

			    json = new JSONObject(builder.toString());	    
			    jsonArray = json.getJSONObject("responseData").getJSONArray("results");

			    results = jsonArray.length();
			    result = null;
			    documentArray = new ArrayList<org.apache.lucene.document.Document>();
			    
			    for (int i = 0; i < results ; i++) {
			    	json = jsonArray.getJSONObject(i);
			    	
			        result = new org.apache.lucene.document.Document();
	
			        result.add(new Field("source", "GVi", Field.Store.YES, Field.Index.UN_TOKENIZED));
			        result.add(new Field("type", "video", Field.Store.YES, Field.Index.UN_TOKENIZED));
			        result.add(new Field("id", json.get("title").toString(), Field.Store.YES, Field.Index.UN_TOKENIZED));
			        result.add(new Field("query", queryString, Field.Store.YES, Field.Index.UN_TOKENIZED));
			        result.add(new Field("rank", Integer.toString(++temp_count + startIndex), Field.Store.YES, Field.Index.UN_TOKENIZED));

			        result.add(new Field("link", json.get("playUrl").toString(), Field.Store.YES, Field.Index.UN_TOKENIZED));
			        result.add(new Field("internal", json.get("url").toString(), Field.Store.YES, Field.Index.UN_TOKENIZED));
			        			        
			        summary = json.get("titleNoFormatting").toString();
			        if (summary.equals("")) summary = "n/a"; 
			        
			        result.add(new Field("summary", summary, Field.Store.YES, Field.Index.TOKENIZED, Field.TermVector.YES));
			        result.add(new Field("width", "n/a".toString(), Field.Store.YES, Field.Index.UN_TOKENIZED));
			        result.add(new Field("height", "n/a".toString(), Field.Store.YES, Field.Index.UN_TOKENIZED));
			        result.add(new Field("fileSize", json.get("duration").toString(), Field.Store.YES, Field.Index.UN_TOKENIZED));
			        result.add(new Field("fileFormat", json.get("videoType").toString(), Field.Store.YES, Field.Index.UN_TOKENIZED));
			        result.add(new Field("thumbUrl", json.get("tbUrl").toString(), Field.Store.YES, Field.Index.UN_TOKENIZED));
			        result.add(new Field("thumbWidth", json.get("tbWidth").toString(), Field.Store.YES, Field.Index.UN_TOKENIZED));
			        result.add(new Field("thumbHeight", json.get("tbHeight").toString(), Field.Store.YES, Field.Index.UN_TOKENIZED));
			        			        
			        result.add(new Field("title", json.get("title").toString(), Field.Store.YES, Field.Index.UN_TOKENIZED));
			        result.add(new Field("description", "n/a", Field.Store.YES, Field.Index.UN_TOKENIZED));
			        result.add(new Field("date", "n/a", Field.Store.YES, Field.Index.UN_TOKENIZED));
			        result.add(new Field("authors", "n/a", Field.Store.YES, Field.Index.UN_TOKENIZED));
			        result.add(new Field("journal", "n/a", Field.Store.YES, Field.Index.UN_TOKENIZED));
			        
			        result.setBoost(400 / temp_count);
			        
			        documentArray.add(result);
			    }
			    
			    this.storage.performIOAction(Storage.WRITE_ACTION, documentArray);
			    this.storage.updateGrid();
    
			    startIndex += max;
			}
		    			
		} catch (IOException e) {
			e.printStackTrace();
		} catch (JSONException e) {
			e.printStackTrace();
		}		
		
		if (this.stop) {
			this.logger.debug("Thread killed.");
            return;
        }
		
		this.logger.debug("Thread ended.");
    }
	
	public void setQueryString(String queryString) {
		this.queryString = queryString;
	}
	
	public String getQueryString() {
		return this.queryString;
	}
	
	public void setCount(int count) {
		this.count = count;
	}
	
	public int getCount() {
		return this.count;
	}
	
	public void setStorage(Storage storage) {
		this.storage = storage;
	}	
	
	public Storage getStorage() {
		return this.storage;
	}

	public WebContext getWctx() {
		return wctx;
	}

	public void setWctx(WebContext wctx) {
		this.wctx = wctx;
	}
}
